package cn.wk.service.impl;

import cn.wk.client.CourseDocClient;
import cn.wk.config.RabbitMQConfig;
import cn.wk.domain.*;
import cn.wk.dto.CourseDto;
import cn.wk.enums.CourseEnum;
import cn.wk.mapper.CourseDetailMapper;
import cn.wk.mapper.CourseMapper;
import cn.wk.mapper.CourseMarketMapper;
import cn.wk.mapper.CourseTypeMapper;
import cn.wk.query.CourseDocQuery;
import cn.wk.query.CourseQuery;
import cn.wk.service.ICourseService;
import cn.wk.util.AjaxResult;
import cn.wk.util.PageList;
import cn.wk.utils.UserContextHolder;
import cn.wk.utils.ValidUtils;
import cn.wk.vo.UserContext;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.validation.Valid;
import java.io.Serializable;
import java.util.Date;
import java.util.List;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wk
 * @since 2021-03-06
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private CourseDetailMapper courseDetailMapper;
    @Autowired
    private CourseMarketMapper courseMarketMapper;
    @Autowired
    private CourseDocClient courseDocClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private CourseTypeMapper courseTypeMapper;


    /**
     * 查询，高级查询，分页
     * @return
     */
    @Override
    public PageList<Course> findList(CourseQuery query) {
        Page<Course> page = new Page<Course>(query.getPage(), query.getRows());
        List<Course> list = courseMapper.findAll(page,query);
        return new PageList<Course>(page.getTotal(), list);
    }

    /**
     * 添加
     * @param dto
     */
    @Override
    public void add(CourseDto dto) {
        //保存t_course，获取其id
        Course course = dto.getCourse();
        CourseEnum courseEnum = CourseEnum.getCourseEnum(course.getGradeId());
        ValidUtils.assertNotNull(courseEnum,"该等级不存在");

        //todo
        //保存部门信息和登录用户信息
        UserContext context = UserContextHolder.context();
        course.setTenantId(context.getTenant_id());
        course.setTenantName(context.getTenant_name());
        course.setUserId(context.getUser_id());
        course.setUserName(context.getUser_name());

        course.setGradeName(courseEnum.getName());
        courseMapper.insert(course);
        //保存t_course_detail表
        CourseDetail courseDetail = dto.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);
        //保存t_course_market表，获取id
        CourseMarket courseMarket = dto.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarketMapper.insert(courseMarket);

    }

    /**
     * 修改
     * @param dto
     */
    @Override
    public void updateCourse(@Valid CourseDto dto) {
        //修改course
        Course course = dto.getCourse();
        CourseEnum courseEnum = CourseEnum.getCourseEnum(course.getGradeId());
        ValidUtils.assertNotNull(courseEnum,"该等级不存在");
        course.setGradeName(courseEnum.getName());
        courseMapper.updateById(course);
        //修改detail
        CourseDetail courseDetail = dto.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.updateById(courseDetail);
        //修改market
        CourseMarket courseMarket = dto.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarketMapper.updateById(courseMarket);
    }

    /**
     * 上线
     * @param id
     */
    @Override
    public void onLineCourse(Long id) {
        Course course = onOrOff(id);
        course.setStatus(1);
        courseMapper.updateById(course);
    }

    /**
     * 下线
     * @param id
     */
    @Override
    public void offLineCourse(Long id) {
        Course course = onOrOff(id);
        course.setStatus(0);
        courseMapper.updateById(course);
    }

    /**
     * 为上线下线做准备
     * @return
     */
    private Course onOrOff(Long id){
        Course course = new Course();
        course.setId(id);
        return course;
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Override
    public boolean deleteById(Serializable id) {
        courseDetailMapper.deleteById(id);
        courseMarketMapper.deleteById(id);
        return super.deleteById(id);
    }

    /**
     * 课程发布和下线
     * @param courseId
     * @param flag
     * @return
     */
    @Override
    public AjaxResult onLineOrOffline(Long courseId, boolean flag) {
        //先判断flag来看其是否为上线还是下线
        //如果已经是上线或者下线的话不能继续去执行，需要抛出异常
        //要更改数据库状态
        //要把其写入es索引库
        Course course = courseMapper.selectById(courseId);
        AjaxResult ajaxResult;
        if(flag){
            //这里代表上架
            //去数据库查其状态
            //然后进行断言
            ValidUtils.assertLongEq(course.getStatus(),1,"课程不能重复上架");
            //创建一个coursedoc对象
            CourseDoc courseDoc = createdCourseDoc(course);
            //调用服务 feign
            ajaxResult = courseDocClient.addOrUpdate(courseDoc);
            //进行断言 如果成功那么就执行下一步，如果失败就抛出异常
            ValidUtils.assertTrueOrFalse(ajaxResult.isSuccess(),"es上架失败");
            //更改数据库状态
            course.setStatus(1);
            courseMapper.updateById(course);
            publishMessage(courseDoc);
        }else {
            ValidUtils.assertLongEq(course.getStatus(),0,"课程不能重复下架");
            ajaxResult = courseDocClient.del(courseId);
            ValidUtils.assertTrueOrFalse(ajaxResult.isSuccess(),"es下架失败");
            //更改数据库状态
            course.setStatus(0);
            courseMapper.updateById(course);
        }
        return ajaxResult;
    }

    /**
     * ES
     * @param courseDocQuery
     * @return
     */
    @Override
    public PageList<CourseDoc> queryCourse(CourseDocQuery courseDocQuery) {
        return courseDocClient.queryCourse(courseDocQuery);
    }

    /**
     * 创建courseDoc对象
     * @param course
     * @return
     */
    private CourseDoc createdCourseDoc(Course course) {
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course,courseDoc);
        //设置上架时间
        courseDoc.setOnlineTime(course.getOnlineTime());
        //查找类型名称
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseDoc.setCourseTypeName(courseType.getName());
        //查找detail
        CourseDetail courseDetail = courseDetailMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseDetail, courseDoc);
        //查找market
        CourseMarket courseMarket = courseMarketMapper.selectById(course.getId());
        BeanUtils.copyProperties(courseMarket, courseDoc);
        return courseDoc;
    }

    /**
     * 发布消息 消息队列
     * @param courseDoc
     */
    public void publishMessage(CourseDoc courseDoc){
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC,"message.sms",courseDoc.getName());
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC,"message.email",courseDoc.getName());
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME_TOPIC,"message.system",courseDoc.getName());
    }
}
